#include "vehicleState.h"

PvehicleState initVehicleState() {
	PvehicleState result = (PvehicleState)malloc(sizeof(VehicleState));
	checkMalloc(result,"vehicleState.c:initVehicleState:1");
	result->pvp = initVehiclePath();
	result->tau = 0;
	result->theta = 0;
	result->jk = 0;
	result->lEdges = 0;
	result->lNodes = 1; //deposito
	result->pathSize=0;
	return result;
}
//TODO quando elimino un vehicleState le istanze di EdgeSol devono rimanere? dipende se lo statye creato e' un surrogato di un originale o se ee' l'originale in se!
//TODO testing
void freeVehicleState(PvehicleState pvs){
	freeVehiclePathHard(pvs->pvp);
	free(pvs);
}

void addEdgeToVehicleState(PedgeID pid, PedgeGraph pe, PvehicleState pvs, bool g_ok) {

	if(addEdgeToVehiclePath(pid, pvs->pvp)) {
		pvs->lNodes++;
		pvs->pathSize++;
	}
	pvs->tau += pe->t;
	if(g_ok) {
		pvs->theta += pe->d;
		pvs->jk += pe->p;
	}
	pvs->lEdges++;
}

//TODO testing !
int removeEdgeFromVehicleState(PedgeID pid, PedgeGraph pe, PvehicleState pvs, bool g_ok) {

	int result = removeEdgeFromVehiclePath(pid, pvs->pvp);

	if (result!=EDGE_NOT_FOUND) {
		pvs->tau -= pe->t;
		pvs->lEdges--;
		if (result==EDGE_REMOVED){
			pvs->lNodes--;
			pvs->pathSize--; //TODO ma perchè sono la stessa cosa Max, convincitene
			if(g_ok) {
				pvs->theta -= pe->d;
				pvs->jk -= pe->p;
			}
		}
	}
	return result;
}

void addEdgeToVehicleStateForConnectionTest(PedgeID pid, PvehicleState pvs){
	addEdgeToVehiclePath(pid, pvs->pvp);
	pvs->lEdges++;
}

void removeEdgeFromVehicleStateForConnectionTest(PedgeID pid, PvehicleState pvs){
	removeEdgeFromVehiclePath(pid, pvs->pvp);
	pvs->lEdges--;
}

//TODO testing
PvehicleState cloneVehicleState(PvehicleState pstate){
	PvehicleState result=(PvehicleState)malloc(sizeof(VehicleState));
	checkMalloc(result,"vehicleState.c:cloneVehicleState:1");
	result->jk=pstate->jk;
	result->lEdges=pstate->lEdges;
	result->lNodes=pstate->lNodes;
	result->pathSize=pstate->pathSize;
	result->pvp=cloneVehiclePathHard(pstate->pvp);
	result->tau=pstate->tau;
	result->theta=pstate->theta;
	return result;
}

bool isConnected(PvehiclePath p_path, int lEdges){
	//resetto tutti i marked a zero
	resetMemory(p_path, DIRECTION_NEXT);
	PedgeSol current;
	while ((current=getNearEdgeInVehiclePath(p_path, DIRECTION_NEXT))!=NULL){
		current->marked=0;
	}
	//parto dal nodo deposito
	int edgeswalked = isConnectedRecursive(0, p_path);
	return(edgeswalked==lEdges);
}

int isConnectedRecursive(int node, PvehiclePath p_path){
	PvehiclePath nearEdges = getEdgesNearNodeInVehiclePath(p_path, node);
	PvehiclePath current = nearEdges;
	/*
	printf("percorso totale ");
	printVehiclePath(stdout,state->pvp);
	printf("intorno di %d: ",node+1);
	printVehiclePath(stdout,nearEdges);
	*/
	int sum=0;
	while ((current=current->next)->edge!=NULL){ //ciclo su tutti gli archi adiacenti a questo
		if (current->edge->marked==current->edge->x){//non possiamo piu' passarci per questo arco
			continue;
		}
		current->edge->marked++;
		sum++;
		/*
		printf("marko ");
		printEdgeID(stdout,current->edge->id);
		printf("\n");
		*/
		sum += isConnectedRecursive(getEdgeIDOtherNode(current->edge->id, node), p_path);
	}
	//libero la memoria occupata da nearEdges
	freeVehiclePathLight(nearEdges);
	return sum;
}

void printVehicleState(FILE* f, PvehicleState pvs, int k) {
	fprintf(f, "Stampa dello stato del veicolo %d\n", k+1);
	printVehiclePath(f, pvs->pvp);
	printVehicleTQJScalars(f, pvs);
}

void printVehicleTQJScalars(FILE* f, PvehicleState pvs) {
	fprintf(f,"Tau=%d, Theta=%d, Jk =%d\n", pvs->tau, pvs->theta, pvs->jk);
}

void printVehicleAllScalars(FILE* f, PvehicleState pvs) {
	fprintf(f,"Tau=%d, Theta=%d, Jk =%d, Ledges=%d, Lnodes=%d\n", pvs->tau, pvs->theta, pvs->jk, pvs->lEdges, pvs->lNodes);
}
